/*
执行ecall指令，触发陷阱并进入内核
从用户进程的 trapframe（陷阱帧）中获取系统调用号；
查找该系统调用号对应的内核处理函数；
调用该内核函数，执行系统调用的具体逻辑；
将返回值存入 trapframe，并最终返回用户态。
不实现具体的调用逻辑，而是找到一个处理函数并进行调用
*/

/*
1.系统调用函数声明（函数指针数组）
2.从 trapframe 解析系统调用号
2.调用对应的系统调用处理函数
*/
#include "types.h"
#include "syscall.h"
#include "proc.h"
// #include"X86.h"

//从用户态的内存中读取参数
//比如说我们现在想要去进行write操作，那么我们就应该先读出文件描述符，以及缓冲地址和字节数，正好对应的write的三个参数

/*
目的：
从用户空间的地址 addr 获取一个 int 类型的值，并将其存储到 ip 指向的内存中。

逻辑：
获取当前进程的指针 curproc。
检查给定的地址 addr 是否在当前进程的内存范围内。
将地址 addr 处的值读取到 ip 中。
如果一切正常，返回 0，否则返回 -1。
获取fd
*/
// int fetchint(uint addr, int *ip){
//     struct proc *curproc = myproc();
//     if(addr >= curproc->sz || addr+4 > curproc->sz)
//         return -1;
//     *ip = *(int*)(addr);
//     return 0;
// }

/*
目的：
从用户空间读取一个以空字符结尾的字符串，并将其指针存储在 pp 中。
逻辑：
获取当前进程的指针 curproc。
检查地址 addr 是否在进程的内存空间范围内。
如果地址有效，将 addr 转换为字符指针 *pp，并在进程的内存空间范围内检查是否有空字符（\0）来标记字符串的结束。
返回字符串的长度（不包括空字符），如果无法找到空字符，则返回 -1。
获取buf和n
*/
// int fetchstr(uint addr, char **pp)
// {
//     char *s, *ep;
//     struct proc *curproc = myproc();

//     if (addr >= curproc->sz)
//         return -1;
//     *pp = (char*)addr;
//     ep = (char*)curproc->sz;
//     for (s = *pp; s < ep; s++) {
//         if (*s == 0)//找到结尾的位置
//             return s - *pp;//返回长度
//     }
//     return -1;
// }

//系统宏列表定义
// extern int sys_chdir(void);
// extern int sys_close(void);
// extern int sys_dup(void);
// extern int sys_exec(void);
// extern int sys_exit(void);
// extern int sys_fork(void);
// extern int sys_fstat(void);
// extern int sys_getpid(void);
// extern int sys_kill(void);
// extern int sys_link(void);
// extern int sys_mkdir(void);
// extern int sys_mknod(void);
// extern int sys_open(void);
// extern int sys_pipe(void);
// extern int sys_read(void);
// extern int sys_sbrk(void);
// extern int sys_sleep(void);
// extern int sys_unlink(void);
// extern int sys_wait(void);
extern int sys_write(uint64 fd, uint64 buf_addr, uint64 len);
// extern int sys_uptime(void);

static int (*syscalls[])(uint64,uint64,uint64) = {//指向要去执行的系统调用的函数
// [SYS_fork]    sys_fork,
// [SYS_exit]    sys_exit,
// [SYS_wait]    sys_wait,
// [SYS_pipe]    sys_pipe,
// [SYS_read]    sys_read,
// [SYS_kill]    sys_kill,
// [SYS_exec]    sys_exec,
// [SYS_fstat]   sys_fstat,
// [SYS_chdir]   sys_chdir,
// [SYS_dup]     sys_dup,
// [SYS_getpid]  sys_getpid,
// [SYS_sbrk]    sys_sbrk,
// [SYS_sleep]   sys_sleep,
// [SYS_uptime]  sys_uptime,
// [SYS_open]    sys_open,
[SYS_write]   sys_write
// [SYS_mknod]   sys_mknod,
// [SYS_unlink]  sys_unlink,
// [SYS_link]    sys_link,
// [SYS_mkdir]   sys_mkdir,
// [SYS_close]   sys_close,
};

// 读取当前的trap并去执行
//将中断的值放入a7寄存器当中，调用sysfile的syswrite
void syscall(struct trapframe *tf) {
    int num = tf->a7;  //  RISC-V 的 tf->a7
    if (num > 0 && num < sizeof(syscalls)/sizeof(syscalls[0]) && syscalls[num]) {
        tf->a0 = syscalls[num](tf->a0,tf->a1,tf->a2);  // 返回值放到 eax
    } else {
        tf->a0 = -1;
    }
}
